import { Reflector } from '@nestjs/core'
import { RedisService } from '@/shared/redis.service'
import { DecoratorEnum, CacheKey, ApiException } from '..'
import { CanActivate, ExecutionContext, HttpStatus, Injectable } from '@nestjs/common'

@Injectable()
export class PermissionAuthGuard implements CanActivate {
  constructor(private readonly reflector: Reflector, private readonly redisService: RedisService) {}

  public async canActivate(context: ExecutionContext): Promise<boolean> {
    try {
      // 获取控制器和处理函数的元数据
      const targets = [context.getHandler(), context.getClass()]
      const permissions = this.reflector.getAllAndOverride<string[]>(DecoratorEnum.PERMISSION_METADATA, targets)
      // 没有设置权限要求，直接允许访问
      if (!permissions) return true
      const request = context.switchToHttp().getRequest<ExpressRequest>()
      // 从请求中获取用户信息 - 增加空值检查
      const user: JwtPayload = Reflect.get(request, 'user')
      if (!user?.userId) throw new Error('用户信息不存在')
      // 获取缓存的用户权限
      const cachePermissions = await this._getCachePermissions(user.userId)
      // 检查是否拥有所需权限
      const hasPermission = permissions.some((perm) => cachePermissions.includes(perm))
      if (!hasPermission) throw new Error('暂无权限访问，请联系管理员')
      return true
    } catch (error: any) {
      throw new ApiException(error.message, HttpStatus.FORBIDDEN)
    }
  }

  /** 从 Redis 获取用户权限缓存 */
  private async _getCachePermissions(userId: string): Promise<string[]> {
    if (!userId) return []
    const jsonStr = await this.redisService.get(`${CacheKey.ADMIN_USER_PERMISSIONS}:${userId}`)
    return jsonStr ? JSON.parse(jsonStr) : []
  }
}
